package org.spiderflow.core.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spiderflow.common.enums.FlowNoticeType;
import org.spiderflow.common.enums.FlowNoticeWay;
import org.spiderflow.core.exception.SpiderException;
import org.spiderflow.core.mapper.FlowNoticeMapper;
import org.spiderflow.core.mapper.SpiderFlowMapper;
import org.spiderflow.core.model.FlowNotice;
import org.spiderflow.core.model.SpiderFlow;
import org.spiderflow.core.utils.ExpressionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zsh
 */
@Service
public class FlowNoticeService extends ServiceImpl<FlowNoticeMapper, FlowNotice> {
    private static final Logger LOGGER = LoggerFactory.getLogger(FlowNoticeService.class);
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    private final SpiderFlowMapper spiderFlowMapper;
    private final EmailSendService emailUtils;
    @Value("${spider.notice.subject:spider-flow流程通知}")
    private String subject;
    @Value("${spider.notice.content.start}")
    private String startContext;
    @Value("${spider.notice.content.end}")
    private String endContext;
    @Value("${spider.notice.content.exception}")
    private String exceptionContext;

    public FlowNoticeService(SpiderFlowMapper spiderFlowMapper, EmailSendService emailUtils) {
        this.spiderFlowMapper = spiderFlowMapper;
        this.emailUtils = emailUtils;
    }

    @Override
    public boolean saveOrUpdate(FlowNotice entity) {
        if (spiderFlowMapper.getCountById(entity.getId()) == 0) {
            throw new SpiderException("没有找到对应的流程");
        }
        return super.saveOrUpdate(entity);
    }

    /**
     * 发送对应的流程通知
     *
     * @param spiderFlow 流程信息
     * @param type       通知类型
     * @author BillDowney
     * @date 2020年4月4日 上午1:37:50
     */
    public void sendFlowNotice(SpiderFlow spiderFlow, FlowNoticeType type) {
        FlowNotice notice = baseMapper.selectById(spiderFlow.getId());
        if (notice != null && !StringUtils.isEmpty(notice.getRecipients())
                && !StringUtils.isEmpty(notice.getNoticeWay())) {
            StringBuilder sendSubject = new StringBuilder(this.subject);
            String contentFormat = switchContentByType(type, notice, sendSubject);
            if (StringUtils.isEmpty(contentFormat)) {
                return;
            }
            // 定义一个上下文变量
            // 放入流程信息
            Map<String, Object> variables = flowToMap(spiderFlow);
            // 放入当前时间
            variables.put("currentDate", this.getCurrentDate());
            contentFormat = contentFormat.replaceAll("\\{", "\\${");
            String content = String.valueOf(ExpressionUtils.execute(contentFormat, variables));
            // 整理收件人
            String recipients = notice.getRecipients();
            for (String recipient : recipients.split(",")) {
                String noticeWay = notice.getNoticeWay();
                String people = recipient;
                // 如果含有":"证明单独配置了发送方式
                if (recipient.contains(":")) {
                    String[] strs = recipient.split(":");
                    noticeWay = strs[0];
                    people = strs[1];
                }
                if (FlowNoticeWay.valueOf(noticeWay, FlowNoticeWay.EMAIL) == FlowNoticeWay.EMAIL) {
                    emailUtils.sendSimpleMail(sendSubject.toString(), content, people);
                    LOGGER.info("sendSimpleMail [{}] -> {}", sendSubject, people);
                }
            }
        }
    }

    private String switchContentByType(FlowNoticeType type, FlowNotice notice, StringBuilder sendSubject) {
        if (type == FlowNoticeType.START_NOTICE && notice.judgeStartNotice()) {
            sendSubject.append(" - 流程开始执行");
            return startContext;
        } else if (type == FlowNoticeType.END_NOTICE && notice.judgeEndNotice()) {
            sendSubject.append(" - 流程执行完毕");
            return endContext;
        } else if (type == FlowNoticeType.EXCEPTION_NOTICE && notice.judgeExceptionNotice()) {
            sendSubject.append(" - 流程发生异常");
            return exceptionContext;
        } else {
            return "";
        }
    }

    private Map<String, Object> flowToMap(SpiderFlow spiderFlow) {
        BeanMap beanMap = BeanMap.create(spiderFlow);
        Map<String, Object> variables = new HashMap<>(beanMap.size());
        for (Object key : beanMap.entrySet()) {
            Map.Entry entry = (Map.Entry) key;
            variables.put(String.valueOf(entry.getKey()), entry.getValue());
        }
        return variables;
    }

    private String getCurrentDate() {
        return sdf.format(new Date());
    }

}
